#include "qmodeldatareport.h"

// constructeur
QModelDataReport::QModelDataReport(QAbstractTableModel *model, QObject *parent) :
    QObject(parent)
{
    sqlmodel = model;
    selectionModel = 0;
    init_parameters();
}

// gestion du model et du body
void QModelDataReport::setListofColumns(QList<int> *columns)
{
    columnsnumber = columns;
}

void QModelDataReport::setColumnWidthPercentage(QList<int> *widthpercent)
{
    columnswidthpercentage=widthpercent;
}

void QModelDataReport::setBodyFont(QFont font)
{
    body_Font=font;
}

void QModelDataReport::setCellsPadding(int padding)
{
    cell_Padding = padding;
}

void QModelDataReport::setCellsAlignment(QList<int> *alignment)
{
    columnAlignment =alignment;
}

void QModelDataReport::setCellsDataFormat(QList<dataFormat> *format)
{
    columnsDataFormat = format;
}

void QModelDataReport::getDefaultDataFormat(dataFormat *dformat)
{
    *dformat = defaultFormat;
}

void QModelDataReport::setAfficheZero(bool a)
{
    afficheZero = a;
}

void QModelDataReport::setSelectionModel(QItemSelectionModel *m)
{
    selectionModel = m;
}

//gestion du header de colonnes
void QModelDataReport::setListofColumnsHeader(QStringList *header)
{
    columnsheader=header;
}

void QModelDataReport::setHeadersFont(QFont font)
{
    headers_Font=font;
}

// gestion du titre de rapport 2/3 de pages (plusieurs lignes possibles)
void QModelDataReport::setTitleFont(QFont font)
{
    title_Font=font;
    if (title_Font.pointSize()>(title_Height-4)) {
        title_Height = title_Font.pointSize()+4; }
 }

void QModelDataReport::setTitleText(QString text)
{
    title_Text=text;
}

void QModelDataReport::setTitleHeight(int height)
{
    if (title_Font.pointSize()<(height-4)) {
        title_Height = height; }
    else {
        title_Height = title_Font.pointSize()+4;
    }
}

 // gestion de l'entete de rapport largeur de page (plusieurs lignes possibles)
void QModelDataReport::setHeaderReportHeight(int height)
{
    if (header_Report_Font.pointSize()<(height-4)) {
        header_Report_Height = height;}
    else {
        header_Report_Height = header_Report_Font.pointSize()+4;
    }
}

void QModelDataReport::setHeaderReportFont(QFont font)
{
    header_Report_Font = font;
    if (header_Report_Font.pointSize()>(header_Report_Height-4)) {
        header_Report_Height = header_Report_Font.pointSize()+4;}
 }

void QModelDataReport::setHeaderReportText(QString text)
{
    header_Report_Text = text;
}

// gestion de l'entete de page en 3 parties (gauche centre droit) sur une seule ligne
void  QModelDataReport::setHeaderPageLeftText(QString text)
{
    header_Page_LeftText = text;
}

void QModelDataReport::setHeaderPageCenterText(QString text)
{
    header_Page_CenterText = text;
}

void QModelDataReport::setHeaderPageRightText(QString text)
{
    header_Page_RightText = text;
}

void QModelDataReport::setHeaderPageFont(QFont font)
{
    header_Page_Font=font;
}

// gestion du pied de page en 2 parties (gauche  droit) sur une seule ligne (le centre est réservé au numéro de page)

void QModelDataReport::setFooterPageLeftText(QString text)
{
    footer_Page_LeftText = text;
}

void QModelDataReport::setFooterPageRightText(QString text)
{
    footer_Page_RightText = text;
}

void QModelDataReport::setFooterPageFont(QFont font)
{
    footer_Page_Font=font;
}

 // gestion du bilan fin de rapport sur la largeur de page et plusieurs lignes possibles
void QModelDataReport::setEndReportText(QString text)
{
    footer_Report_Text = text;
}

void QModelDataReport::setEndReportHeight(int height)
{
    if (footer_Report_Font.pointSize()<(height-4)) {
        footer_Report_Height = height;}
    else {
        footer_Report_Height = footer_Report_Font.pointSize()+4;
    }
}

void QModelDataReport::setEndReportFont(QFont font)
{
    footer_Report_Font = font;
    if (footer_Report_Font.pointSize()>(footer_Report_Height-4)) {
        footer_Report_Height = footer_Report_Font.pointSize()+4;}
}
// calcul des totaux des colonnes numériques

void QModelDataReport::getSumOfnumColumns(QList<QVariant> *Sum)  {
    // initialise les totaux à 0
    double total =0;
    for(int i=0;i<Sum->size();i++)
    {
        Sum->replace(i,0);
    }
    //  effectue la somme de chaque colonne
    for(int i=0;i<sqlmodel->rowCount();i++)
    {
        for(int j=0;j<Sum->size();j++)
        {
            total=(Sum->at(j).toDouble()+sqlmodel->index(i,columnsnumber->at(j)).data().toDouble());
            Sum->replace(j,total);
        }
    }
    Sum->append(sqlmodel->rowCount());

}

// gestion de l'impression et contruction du rapport

void QModelDataReport::setOutputFormat(QPrinter::OutputFormat support)
{
    print_support=support;
}

void QModelDataReport::model_print()
{
    // test des paramatres definis ou non
    if (!parameters_test()) {
        return;
    }
    // definition du support d'impression
    printer.setOutputFormat(print_support);
    QPrintDialog *dialog = new QPrintDialog(&printer);
    dialog->setWindowTitle(title_Text);
    if (dialog->exec() == QDialog::Accepted)
    {
        // creation du painter et debut de dessin (d'impression)
        painter.begin(&printer);
        page_Height = printer.pageRect().height();
        page_Width = printer.pageRect().width();
        header_Height = headers_Font.pointSize()+2*cell_Padding+2;
        header_Page_Height = header_Page_Font.pointSize()+10;
        footer_Page_Height = footer_Page_Font.pointSize()+10;
        line_Height = body_Font.pointSize()+2*cell_Padding+2;
        body_top=title_Height+header_Report_Height+header_Page_Height+header_Height;
        body_Height = page_Height - body_top -footer_Page_Height;
        Number_of_lines = body_Height / line_Height;
        line_Num=0;
        page_Num=0;
        // conversion des widthpercentage en widthpixel pour chaque colonne
        width_conversion();
        // Titre
        draw_title();
        //entete du rapport
        draw_report_header();
        //entete de chaque page
        draw_page_header();
        // En tète colonnes
        draw_headers();
        // corps du rapport
        draw_body();
        // bilan du rapport
        draw_report_footer();
        // fin du job impression
        draw_page_footer();
        painter.end();
    }

}

// procédures privéesinternes à la classe datareport
void QModelDataReport::init_parameters()
{
    //dataFormat *defaultdataformat = new dataFormat;
    dataFormat defaultFormat;


    defaultFormat.strFormat="%1";
    defaultFormat.typeFormat=typeIsQString;
    defaultFormat.fieldwidthFormat=0;
    defaultFormat.fillFormat=" ";
    for(int i=0;i<sqlmodel->columnCount();i++)
     {
        defaultlistcolumn << i;
        defaultlistwidth << (100/sqlmodel->columnCount());
        defaultlistaligment << Qt::AlignCenter ;
        defaultlistheader << QVariant(i).toString();
        defaultlistformat << defaultFormat;
    }
    setListofColumns(&defaultlistcolumn);
    setColumnWidthPercentage(&defaultlistwidth);
    setCellsAlignment(&defaultlistaligment);
    setListofColumnsHeader(&defaultlistheader);
    setCellsDataFormat(&defaultlistformat);

    setBodyFont(QFont("Arial",8,0));
    setCellsPadding(2);

    setHeadersFont(QFont("Arial",9,2,true));
    setTitleFont(QFont("Arial",14,2));
    setTitleText("Edition de l'impression");
    setTitleHeight(40);
    setHeaderReportText("");
    setHeaderReportFont(QFont("Arial",8,1));
    setHeaderReportHeight(12);
    setHeaderPageLeftText(QDate::currentDate().toString("dd/MM/yyyy"));
    setHeaderPageCenterText("");
    setHeaderPageRightText(QTime::currentTime().toString("HH:mm:ss"));
    setHeaderPageFont(QFont("Arial",6,1));
    setFooterPageLeftText(QDate::currentDate().toString("dd/MM/yyyy"));
    setFooterPageRightText(QTime::currentTime().toString("HH:mm:ss"));
    setFooterPageFont(QFont("Arial",6,1));
    setEndReportText("");
    setEndReportFont(QFont("Arial",8,1));
    setEndReportHeight(12);
    print_support = QPrinter::NativeFormat;

    afficheZero = true;
}

bool QModelDataReport::parameters_test()
{
    // vérification de la liste des headers
    if (columnsheader->size()!=columnsnumber->size()) {
        defaultlistheader.clear();
        for(int i=0;i<columnsnumber->size();i++) {
            defaultlistheader << QVariant(columnsnumber->at(i)).toString();
        }
        setListofColumnsHeader(&defaultlistheader);
    }
    // vérification de la liste des width
    if(columnswidthpercentage->size()!=columnsnumber->size()) {
        defaultlistwidth.clear();
        for(int i=0;i<columnsnumber->size();i++) {
            defaultlistwidth << (100/columnsnumber->size());
        }
        setColumnWidthPercentage(&defaultlistwidth);
    }
    // vérification des alignments
    if(columnAlignment->size()!=columnsnumber->size()) {
        defaultlistaligment.clear();
        for(int i=0;i<columnsnumber->size();i++) {
            defaultlistaligment << Qt::AlignCenter;
        }
        setCellsAlignment(&defaultlistaligment);
    }
    // vérification des formats
    if(columnsDataFormat->size()!=columnsnumber->size()) {
        defaultlistformat.clear();
        for(int i=0;i<columnsnumber->size();i++) {
            defaultlistformat << defaultFormat;
        }
        setCellsDataFormat(&defaultlistformat);
    }
    return true;

}

void QModelDataReport::width_conversion()
{
    columnswidthpixel.clear();
    for(int i=0;i<columnswidthpercentage->size();i++) {
        columnswidthpixel << (page_Width*columnswidthpercentage->at(i)/100);
    }
}

void QModelDataReport::draw_title()
{
    int sixthpage = page_Width / 6;
    painter.setFont(title_Font);
    painter.fillRect(sixthpage,2,page_Width-2*sixthpage,title_Height-4,QBrush(Qt::lightGray));
    painter.drawText(sixthpage,2,page_Width-2*sixthpage,title_Height-4,Qt::AlignCenter,title_Text);
}

void QModelDataReport::draw_report_header()
{
    painter.setFont(header_Report_Font);
    int posy =title_Height;
    painter.drawText(0,posy,page_Width,header_Report_Height,Qt::AlignLeft | Qt::AlignVCenter,header_Report_Text);
}

void QModelDataReport::draw_page_header()
{
    painter.setFont(header_Page_Font);
    int posy;
    if (page_Num==0) {
        posy=title_Height+header_Report_Height;
    }
    else {
        posy=0;
    }
    int thirdpage = page_Width/3;
    painter.drawText(0,posy,thirdpage,header_Page_Height,Qt::AlignLeft | Qt::AlignVCenter,header_Page_LeftText);
    painter.drawText(thirdpage,posy,thirdpage,header_Page_Height,Qt::AlignCenter,header_Page_CenterText);
    painter.drawText(2*thirdpage,posy,thirdpage,header_Page_Height,Qt::AlignRight | Qt::AlignVCenter,header_Page_RightText);
}

void QModelDataReport::draw_headers()
{
    painter.setFont(headers_Font);
    int posx =0;
    int posy;
    if (page_Num==0) {
        posy=title_Height+header_Report_Height+header_Page_Height;
    }
    else {
        posy=header_Page_Height;
    }
    for (int i = 0; i < columnsnumber->size(); ++i) {
        painter.drawRect(posx,posy,columnswidthpixel.at(i),header_Height);
        painter.drawText(cell_Padding+posx,posy+cell_Padding,columnswidthpixel.at(i)-2*cell_Padding,header_Height-2*cell_Padding+2,columnAlignment->at(i),columnsheader->at(i));
        posx=posx+columnswidthpixel.at(i);
    }
}

void QModelDataReport::draw_body()
{
    QVariant data ;
    QString param;
    QChar fillchar;
    QString fillstring;
    bool printOnlySelection = selectionModel != 0;
    bool isSelected = true;

    for(int i=0;i<sqlmodel->rowCount();i++)
    {
        if(printOnlySelection)
            isSelected = selectionModel->isRowSelected(i,QModelIndex()) ;

        if(!printOnlySelection || isSelected){
            painter.setFont(body_Font);
            int posx=0;
            for (int j = 0; j < columnsnumber->size(); ++j)
            {
                data = sqlmodel->index(i,columnsnumber->at(j)).data();
                fillstring = columnsDataFormat->at(j).fillFormat;
                if (fillstring!="") {fillchar = QVariant(columnsDataFormat->at(j).fillFormat.left(1)).toChar().toLatin1();}
                else {fillchar = QLatin1Char(' ');}

                switch (columnsDataFormat->at(j).typeFormat) {
                case typeIsQString:
                    param=columnsDataFormat->at(j).strFormat.arg(data.toString(),columnsDataFormat->at(j).fieldwidthFormat,fillchar);
                    break;
                case typeIsInteger:      // donnée de type int en base 10
                     param=columnsDataFormat->at(j).strFormat.arg(data.toInt(),columnsDataFormat->at(j).fieldwidthFormat,10,fillchar);
                    break;
                case typeIsHexa:  //donnée en int affichée en hexa
                    param=columnsDataFormat->at(j).strFormat.arg(data.toInt(),columnsDataFormat->at(j).fieldwidthFormat,16,fillchar);
                    break;
                case typeIsCurrency:        // données de type monétaire (décimal formaté en +/- 9999.99)
                    param=columnsDataFormat->at(j).strFormat.arg(data.toDouble(),columnsDataFormat->at(j).fieldwidthFormat,'f',2,fillchar);
                    break;
                case typeIsDouble:        //donnée de type décimal affichée +/- 9999.999
                      param=columnsDataFormat->at(j).strFormat.arg(data.toDouble(),columnsDataFormat->at(j).fieldwidthFormat,'f',3,fillchar);
                    break;
                case typeIsDoubleSciences: // donnée de type décimal affichée +/- 9.999 E+/-999
                      param=columnsDataFormat->at(j).strFormat.arg(data.toDouble(),columnsDataFormat->at(j).fieldwidthFormat,'E',2,fillchar);
                    break;
                case typeIsQDate:
                    param=columnsDataFormat->at(j).strFormat.arg(data.toDate().toString(fillstring));
                    break;
                case typeIsQTime:
                    param=columnsDataFormat->at(j).strFormat.arg(data.toTime().toString(fillstring));
                    break;
                case typeIsQDateTime:
                    param=columnsDataFormat->at(j).strFormat.arg(data.toDateTime().toString(fillstring));
                    break;

                default:
                    param=QString("%1").arg(data.toString(),0,QLatin1Char( ' ' ));
                    break;
                }

                if(columnsDataFormat->at(j).typeFormat == typeIsCurrency && data.toDouble() == 0 && !afficheZero)
                    param = "";

                painter.drawRect(posx,body_top+line_Num*line_Height,columnswidthpixel.at(j),line_Height);
                painter.drawText(posx+cell_Padding,body_top+line_Num*line_Height+cell_Padding,columnswidthpixel.at(j)-2*cell_Padding,line_Height-2*cell_Padding+2,columnAlignment->at(j),param);
                posx=posx+columnswidthpixel.at(j);
            }
            next_line();
        }
    }
}

void QModelDataReport::draw_page_footer()
{
    int posy =page_Height-footer_Page_Height;
    int thirdpage = page_Width/3;
    painter.setFont(footer_Page_Font);
    painter.drawText(0,posy,thirdpage,footer_Page_Height,Qt::AlignLeft | Qt::AlignVCenter,footer_Page_LeftText);
    painter.drawText(thirdpage,posy,thirdpage,footer_Page_Height,Qt::AlignCenter,"- "+QVariant(page_Num+1).toString()+" -");
    painter.drawText(2*thirdpage,posy,thirdpage,footer_Page_Height,Qt::AlignRight | Qt::AlignVCenter,footer_Page_RightText);
}

void QModelDataReport::draw_report_footer()
{
    painter.setFont(footer_Report_Font);
    int  posy=body_top+line_Num*line_Height;
    painter.drawText(0,posy,page_Width,footer_Report_Height,Qt::AlignLeft | Qt::AlignVCenter,footer_Report_Text);
}

void QModelDataReport::next_line()
{
    line_Num=line_Num+1;
    if (line_Num>=Number_of_lines)
        {
            draw_page_footer();
            page_Num=page_Num+1;
            body_top=header_Page_Height+header_Height;
            body_Height = page_Height - body_top -footer_Page_Height;
            Number_of_lines = body_Height / line_Height;
            line_Num=0;
            printer.newPage();
            draw_page_header();
            draw_headers();
        }
}


